{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40721ca7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 评分明细 ===\n",
      "扣非净利润同比增长率: 38.03 得分: 3\n",
      "销售净利率: 9.97 得分: 1\n",
      "ROE ttm(扣非): 18.257014062935117 得分: 3\n",
      "资产负债率 < 50% 得分: 0\n",
      "每股经营现金流 > 0 得分: 1\n",
      "-----------------------\n",
      "得分：8\n",
      "净利润 ttm：419.59\n",
      "扣非净利润 ttm：392.55\n",
      "PE: 13.5\n",
      "PEmin: 10.8\n",
      "PEmax: 16.2\n",
      "最小市值: 4531.572\n",
      "合理市值: 566446500000.0\n",
      "最大市值: 6797.358\n",
      "最小股价: 59.043283387622154\n",
      "低估范围股价: 59.043283387622154 ~ 66.42369381107493\n",
      "合理股价：73.80410423452768\n",
      "最大股价: 88.56492508143323\n"
     ]
    }
   ],
   "source": [
    "import akshare as ak\n",
    "import pandas as pd\n",
    "\n",
    "stock_code = \"000001\"\n",
    "\n",
    "def parse_amount(x):\n",
    "    if pd.isna(x):\n",
    "        return None\n",
    "    if isinstance(x, (int, float)):\n",
    "        return x\n",
    "    x = str(x).replace(\",\", \"\").strip()\n",
    "    sign = -1 if x.startswith(\"-\") else 1\n",
    "    x = x.lstrip(\"+-\")\n",
    "    if \"亿\" in x:\n",
    "        return sign * float(x.replace(\"亿\", \"\")) * 1e8\n",
    "    elif \"万\" in x:\n",
    "        return sign * float(x.replace(\"万\", \"\")) * 1e4\n",
    "    elif x == \"\":\n",
    "        return None\n",
    "    else:\n",
    "        try:\n",
    "            return sign * float(x)\n",
    "        except:\n",
    "            return None\n",
    "\n",
    "# 获取利润表（按单季度）\n",
    "profit_df = ak.stock_financial_abstract_ths(symbol=stock_code, indicator=\"按单季度\")\n",
    "profit_df['净利润'] = profit_df['净利润'].apply(parse_amount)\n",
    "profit_df['扣非净利润'] = profit_df['扣非净利润'].apply(parse_amount)\n",
    "profit_df['报告期'] = pd.to_datetime(profit_df['报告期'])\n",
    "\n",
    "# 获取资产负债表（按报告期）\n",
    "balance_df = ak.stock_financial_debt_ths(symbol=stock_code, indicator=\"按报告期\")\n",
    "balance_df['*归属于母公司所有者权益合计'] = balance_df['*归属于母公司所有者权益合计'].apply(parse_amount)\n",
    "balance_df['报告期'] = pd.to_datetime(balance_df['报告期'])\n",
    "\n",
    "# 计算扣非ROE TTM\n",
    "non_net_profit_ttm = (\n",
    "    profit_df.sort_values(\"报告期\", ascending=False)\n",
    "    .head(4)['扣非净利润']\n",
    "    .sum()\n",
    ")\n",
    "# 计算非扣非 roe\n",
    "net_profit_ttm = (\n",
    "    profit_df.sort_values(\"报告期\", ascending=False)\n",
    "    .head(4)['净利润']\n",
    "    .sum()\n",
    ")\n",
    "\n",
    "\n",
    "equity_latest = (\n",
    "    balance_df.sort_values(\"报告期\", ascending=False)\n",
    "    .iloc[0]['*归属于母公司所有者权益合计']\n",
    ")\n",
    "\n",
    "if equity_latest and equity_latest != 0:\n",
    "    roe_ttm_value = net_profit_ttm / equity_latest * 100\n",
    "else:\n",
    "    roe_ttm_value = None\n",
    "\n",
    "# 获取单季度最新一行其他指标\n",
    "df_quarter = ak.stock_financial_abstract_ths(symbol=stock_code, indicator=\"按单季度\")\n",
    "df_quarter['报告期'] = pd.to_datetime(df_quarter['报告期'])\n",
    "latest_row = df_quarter.sort_values(\"报告期\").iloc[-1]\n",
    "\n",
    "def to_float(val):\n",
    "    if pd.isna(val):\n",
    "        return None\n",
    "    s = str(val).strip().rstrip(\"%\")\n",
    "    try:\n",
    "        return float(s)\n",
    "    except:\n",
    "        return None\n",
    "\n",
    "kfjl_yoy = to_float(latest_row.get(\"扣非净利润同比增长率\", None))\n",
    "xsjl = to_float(latest_row.get(\"销售净利率\", None))\n",
    "roe = roe_ttm_value  # 替换为计算的ROE TTM\n",
    "asset_liab_ratio = to_float(latest_row.get(\"资产负债率\", None))\n",
    "cash_flow = to_float(latest_row.get(\"每股经营现金流\", None))\n",
    "\n",
    "score_kfjl = 0\n",
    "score_xsjl = 0\n",
    "score_roe = 0\n",
    "score_risk = 0\n",
    "\n",
    "if kfjl_yoy is not None:\n",
    "    if kfjl_yoy >= 20:\n",
    "        score_kfjl = 3\n",
    "    elif kfjl_yoy >= 15:\n",
    "        score_kfjl = 2\n",
    "    elif kfjl_yoy >= 8:\n",
    "        score_kfjl = 1\n",
    "\n",
    "if xsjl is not None:\n",
    "    if xsjl >= 14:\n",
    "        score_xsjl = 3\n",
    "    elif xsjl >= 10:\n",
    "        score_xsjl = 2\n",
    "    elif xsjl >= 6:\n",
    "        score_xsjl = 1\n",
    "\n",
    "if roe is not None:\n",
    "    if roe >= 16:\n",
    "        score_roe = 3\n",
    "    elif roe >= 12:\n",
    "        score_roe = 2\n",
    "    elif roe >= 8:\n",
    "        score_roe = 1\n",
    "\n",
    "if asset_liab_ratio is not None and asset_liab_ratio < 50:\n",
    "    score_risk += 1\n",
    "if cash_flow is not None and cash_flow > 0:\n",
    "    score_risk += 1\n",
    "\n",
    "total_score = score_kfjl + score_xsjl + score_roe + score_risk\n",
    "\n",
    "\n",
    "print(\"=== 评分明细 ===\")\n",
    "print(f\"扣非净利润同比增长率: {kfjl_yoy} 得分: {score_kfjl}\")\n",
    "print(f\"销售净利率: {xsjl} 得分: {score_xsjl}\")\n",
    "print(f\"ROE ttm(扣非): {roe} 得分: {score_roe}\")\n",
    "print(f\"资产负债率 < 50% 得分: {1 if asset_liab_ratio is not None and asset_liab_ratio < 50 else 0}\")\n",
    "print(f\"每股经营现金流 > 0 得分: {1 if cash_flow is not None and cash_flow > 0 else 0}\")\n",
    "print(\"-----------------------\")\n",
    "print(f\"得分：{total_score}\")\n",
    "net_profit_ttm_option = net_profit_ttm\n",
    "# net_profit_ttm_option = non_net_profit_ttm\n",
    "default_pe = 15 # 默认pe\n",
    "avg_pe = default_pe * 0.9\n",
    "PEmin = avg_pe * 0.8\n",
    "PEminDuring = avg_pe * 0.9\n",
    "PEmax = avg_pe * 1.2\n",
    "mktCapMin = PEmin * net_profit_ttm_option / 100000000\n",
    "mktCapMax = PEmax * net_profit_ttm_option / 100000000\n",
    "floatCount = 76.75\n",
    "amountMin = mktCapMin / floatCount \n",
    "amoutMax = mktCapMax / floatCount\n",
    "amountMinDuring = PEminDuring * net_profit_ttm_option / 100000000 / floatCount\n",
    "amountAvg = avg_pe * net_profit_ttm_option / 100000000 / floatCount\n",
    "print(f'净利润 ttm：{ net_profit_ttm / 10000 / 10000 }')\n",
    "print(f'扣非净利润 ttm：{ non_net_profit_ttm / 10000 / 10000 }')\n",
    "print(f\"PE: {avg_pe}\")\n",
    "print(f\"PEmin: {PEmin}\")\n",
    "print(f\"PEmax: {PEmax}\")\n",
    "print(f\"最小市值: {mktCapMin}\")\n",
    "print(f\"合理市值: {avg_pe * net_profit_ttm_option / 10000 / 10000}\") # 没有技术壁垒，想像不够\n",
    "print(f\"最大市值: {mktCapMax}\")\n",
    "print(f\"最小股价: {amountMin}\")\n",
    "print(f\"低估范围股价: {amountMin} ~ {amountMinDuring}\")\n",
    "print(f'合理股价：{amountAvg}')\n",
    "print(f\"最大股价: {amoutMax}\")\n",
    "print(f\"盈利幅度：{ (1.15 / 0.85  - 1) * 0.65 }\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
